# Introduction

Evergreen ships with an all-new, extensible theming architecture that lets end-users customize the look and feel of the components in Evergreen as you want. You can target arbitrary styles and states of each component to achieve maximum flexibility and alignment with your brand. This page goes over some of the options and background of the theming architecture, and how you can leverage it in your apps.

# Default Theme

Evergreen currently ships with one theme representing our current brand. You can extend it with your own styles or create your own theme from scratch by taking a look at how the `defaultTheme` object is constructed.

```jsx
<ThemeProvider value={defaultTheme}>
  <Pane display="flex" flexDirection="column" alignItems="flex-start">
    <Heading marginBottom={majorScale(2)}>Using Default Theme</Heading>
    <Button marginBottom={majorScale(2)} appearance="primary">
      Confirm
    </Button>
    <Alert marginBottom={majorScale(2)} title="There was an issue processing your data!" intent="warning" />
    <Checkbox checked={true} marginBottom={majorScale(2)} label="I agree" />
  </Pane>
</ThemeProvider>
```

# Theme API Overview

Most components go by the following API, which takes inspiration from the `useStyleConfig` API pioneered by the folks over at [Chakra UI](https://chakra-ui.com/). There are three parts to the theming system:

- `baseStyle`: These are the default "base" styles applied to a component. This includes targeting pseudo-states that some components offer, including `_hover`, and `_active`.
- `appearances`: These are the custom styles that you can apply to a component based on the `appearance` prop. Note that **some** components don't have this.
- `sizes`: These are additional props that you can alias via a `size` property. Again, note that **some** components don't have this, and you can only configure `baseStyle`.

> While these guidelines are generally accurate for most components, there are some edge cases that might not follow
> this exact shape. If you're trying to theme a component and it isn't quite working correctly, try taking a look at how we implement the theme internally.
> Component theme files can be found at <a href="https://github.com/segmentio/evergreen/tree/master/src/themes/default/components"><inlineCode>src/themes/default/components/[component].js</inlineCode></a>.

An example implementation that leverages some of these props to create a custom button is below:

```jsx
function CustomButtonExample() {
  const theme = mergeTheme(defaultTheme, {
    components: {
      Button: {
        baseStyle: {
          color: 'white',
          paddingX: 12,
          paddingY: 8,
          borderRadius: 5,
          backgroundColor: 'indianred',
          selectors: {
            _hover: {
              backgroundColor: 'firebrick',
            },
            _active: {
              backgroundColor: 'darkred',
            },
            _focus: {
              boxShadow: '0 0 0 2px lightcoral',
            },
          }
        },
      },
    },
  })

  return (
    <ThemeProvider value={theme}>
      <Button appearance="none">Custom Button</Button>
    </ThemeProvider>
  )
}
```

# Custom Appearances

The theming API also supports custom appearances, so you can bring your own verbiage and nomenclature to how you want to define Evergreen styles. We are still working out TypeScript support for this, so use at your own discretion! For the example below, we are going to take those same styles, and apply them to respond to a prop `appearance="superdanger"`.

```jsx
function CustomAppearancesExample() {
  const theme = mergeTheme(defaultTheme, {
    components: {
      Button: {
        appearances: {
          superdanger: {
            color: 'white',
            paddingX: 12,
            paddingY: 8,
            borderRadius: 5,
            backgroundColor: 'indianred',
            selectors: {
              _hover: {
                backgroundColor: 'firebrick',
              },
              _active: {
                backgroundColor: 'darkred',
              },
              _focus: {
                boxShadow: '0 0 0 2px lightcoral',
              },
            }
          },
        },
      },
    },
  })

  return (
    <ThemeProvider value={theme}>
      <Button appearance="superdanger">Custom Button</Button>
    </ThemeProvider>
  )
}
```

# Theme Utilities

`mergeTheme` is a utility function that allows you to deeply merge a partial `Theme` object onto another one, such as the `defaultTheme`, without having to do multiple object spreads (i.e. `...defaultTheme, ...defaultTheme.colors, ...defaultTheme.components`). If you're using TypeScript, it returns a type union of `DestinationTheme & SourceTheme`, where `DestinationTheme` is the first argument (such as `defaultTheme`) and `SourceTheme` is the type of the second argument (which can be explicitly or implicitly typed).

`useTheme` is a hook that returns the current theme object from the `ThemeProvider`. It is generically typed, so you can use it to provide a strongly typed version of your own theme.

# Theme Shape

All in all, the shape of the theme object looks as follows. Use this as your baseline direction for piecing together and building theme objects. For TypeScript users, you should be able to use parts of the generic [Theme](https://github.com/segmentio/evergreen/blob/11fd42f489b4784d6e82acae9bd27133be898148/index.d.ts#L311-L324) for constructing your own theme, or [DefaultTheme](https://github.com/segmentio/evergreen/blob/master/index.d.ts#L368-L388) which is a more specific version of the interface for `defaultTheme`.

```js readonly
export default {
  colors,
  fills,
  intents,
  radii,
  shadows,
  fontFamilies: {
    display: '...',
    ui: '...',
    mono: '...',
  },
  fontSizes: {
    /* ... */
  },
  fontWeights: {
    /* ... */
  },
  letterSpacings: {
    /* ... */
  },
  lineHeights: [
    /* ... */
  ],
  zIndices,
  components: {
    Alert: {
      /* ... */
    },
    Avatar: {
      /* ... */
    },
    Badge: {
      /* ... */
    },
    Button: {
      /* ... */
    },
    Card: {
      /* ... */
    },
    Checkbox: {
      /* ... */
    },
    Code: {
      /* ... */
    },
    DialogBody: {
      /* ... */
    },
    DialogFooter: {
      /* ... */
    },
    DialogHeader: {
      /* ... */
    },
    Group: {
      /* ... */
    },
    Heading: {
      /* ... */
    },
    Icon: {
      /* ... */
    },
    InlineAlert: {
      /* ... */
    },
    Input: {
      /* ... */
    },
    Label: {
      /* ... */
    },
    List: {
      /* ... */
    },
    Link: {
      /* ... */
    },
    MenuItem: {
      /* ... */
    },
    Option: {
      /* ... */
    },
    Pane: {
      /* ... */
    },
    Paragraph: {
      /* ... */
    },
    Radio: {
      /* ... */
    },
    Select: {
      /* ... */
    },
    Spinner: {
      /* ... */
    },
    Switch: {
      /* ... */
    },
    Tab: {
      /* ... */
    },
    Table: {
      /* ... */
    },
    TableCell: {
      /* ... */
    },
    TableHead: {
      /* ... */
    },
    TableRow: {
      /* ... */
    },
    TagInput: {
      /* ... */
    },
    Text: {
      /* ... */
    },
    TextDropdownButton: {
      /* ... */
    },
    Tooltip: {
      /* ... */
    },
  },
}
```
